﻿using NovoDataBase;
using NovoSerDesEva;
using OfficeOpenXml;
using Sunny.UI;
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.IO;
using System.IO.Packaging;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;



namespace NovoSerDes.Funcs
{
    [Serializable]
    public class LogData : ILogData
    {
        private static LogData instance;
        private DataSet dsLog;
        private DataTable dtLogAllData;

        private static volatile UInt32 LogNum;
        private static volatile bool isMonitoring = false;
        private static readonly object lockObject = new object();
        private static CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
        private static Thread monitorLogNumThread;
        private static bool monitorLogNumResult = false;

        private LogData()
        {

            dsLog = new DataSet();

            dtLogAllData = new DataTable();
            dtLogAllData.Columns.Add("ChipAddr", typeof(UInt32));
            dtLogAllData.Columns.Add("Type", typeof(string));
            dtLogAllData.Columns.Add("Addr", typeof(UInt16));
            dtLogAllData.Columns.Add("Value", typeof(string));
            dtLogAllData.Columns.Add("IsValid", typeof(Boolean));
            dtLogAllData.Columns.Add("Time", typeof(string));
            dtLogAllData.TableName = "Log";
        }
        
        public static LogData Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new LogData();
                }
                return instance;
            }
        }


        public DataSet GetDataSet
        {
            get
            {
                lock (lockObject)
                {
                    return dsLog;
                }
            }
        }

        public DataTable GetDataTableAllData
        {
            get
            {
                lock (lockObject)
                {
                    return dtLogAllData;
                }
            }
        }
        public event EventHandler<string[]> AddDataToTxtBox;
        public bool AddData(string[] data)
        {
            lock (lockObject)
            {
                bool isExist = false;
                foreach (DataTable dataTable in dsLog.Tables)
                {
                    if (dataTable.TableName.ToUpper().Contains(data[0].ToUpper()))
                    {
                        DataRow newRow = dataTable.NewRow();
                        newRow[0] = data[0].ToUInt();
                        newRow[1] = data[1];
                        newRow[2] = data[2].ToUInt();   // 假设有一个 ToInt() 方法将字符串转换为整数
                        newRow[3] = data[3];   // 假设有一个 ToInt() 方法将字符串转换为整数
                        newRow[4] = data[4].ToBoolean(); // 假设有一个 ToBoolean() 方法将字符串转换为布尔值
                        newRow[5] = data[5];
                        dataTable.Rows.Add(newRow);   // 添加新行到数据表中

                        DataRow dataRow = dtLogAllData.NewRow();
                        dataRow[0] = data[0].ToUInt();
                        dataRow[1] = data[1];
                        dataRow[2] = data[2].ToUInt();
                        dataRow[3] = data[3];
                        dataRow[4] = data[4].ToBoolean();
                        dataRow[5] = data[5];
                        dtLogAllData.Rows.Add(dataRow);
                        return true;
                    }
                }
                if (!isExist)
                {
                    DataTable dt = new DataTable();
                    dt.Columns.Add("ChipAddr", typeof(UInt32));
                    dt.Columns.Add("Type", typeof(string));
                    dt.Columns.Add("Addr", typeof(UInt16));
                    dt.Columns.Add("Value", typeof(string));
                    dt.Columns.Add("IsValid", typeof(Boolean));
                    dt.Columns.Add("Time", typeof(string));

                    DataRow dataRow = dt.NewRow();
                    dataRow[0] = data[0].ToUInt();
                    dataRow[1] = data[1];
                    dataRow[2] = data[2].ToUInt();
                    dataRow[3] = data[3];
                    dataRow[4] = data[4].ToBoolean();
                    dataRow[5] = data[5];
                    dt.Rows.Add(dataRow);

                    DataRow newRow = dtLogAllData.NewRow();
                    newRow[0] = data[0].ToUInt();
                    newRow[1] = data[1];
                    newRow[2] = data[2].ToUInt();
                    newRow[3] = data[3];
                    newRow[4] = data[4].ToBoolean();
                    newRow[5] = data[5];
                    dtLogAllData.Rows.Add(newRow);

                    dt.TableName = data[0];
                    dsLog.Tables.Add(dt);
                    return true;
                }
            }
            return false;
        }

        public bool AddData(uint chipAddr, string rw, uint addr, string value, bool isValid, string time)
        {
            lock (lockObject)
            {
                bool isExist = false;
                foreach (DataTable dataTable in dsLog.Tables)
                {
                    if (dataTable.TableName.ToUpper().Contains(chipAddr.ToString().ToUpper()))
                    {
                        DataRow dataRow = dataTable.NewRow();
                        dataRow[0] = chipAddr;
                        dataRow[1] = rw;
                        dataRow[2] = addr;
                        dataRow[3] = value;
                        dataRow[4] = isValid;
                        dataRow[5] = time;
                        dataTable.Rows.Add(dataRow);

                        DataRow newRow = dtLogAllData.NewRow();
                        newRow[0] = chipAddr;
                        newRow[1] = rw;
                        newRow[2] = addr;
                        newRow[3] = value;
                        newRow[4] = isValid;
                        newRow[5] = time;
                        dtLogAllData.Rows.Add(newRow);
                        return true;
                    }

                }
                if (!isExist)
                {
                    DataTable dt = new DataTable();
                    dt.Columns.Add("ChipAddr", typeof(UInt32));
                    dt.Columns.Add("Type", typeof(string));
                    dt.Columns.Add("Addr", typeof(UInt16));
                    dt.Columns.Add("Value", typeof(string));
                    dt.Columns.Add("IsValid", typeof(Boolean));
                    dt.Columns.Add("Time", typeof(string));

                    DataRow dataRow = dt.NewRow();
                    dataRow[0] = chipAddr;
                    dataRow[1] = rw;
                    dataRow[2] = addr;
                    dataRow[3] = value;
                    dataRow[4] = isValid;
                    dataRow[5] = time;
                    dt.Rows.Add(dataRow);

                    DataRow newRow = dtLogAllData.NewRow();
                    newRow[0] = chipAddr;
                    newRow[1] = rw;
                    newRow[2] = addr;
                    newRow[3] = value;
                    newRow[4] = isValid;
                    newRow[5] = time;
                    dtLogAllData.Rows.Add(newRow);
                    dt.TableName = chipAddr.ToString();
                    dsLog.Tables.Add(dt);
                    return true;
                }

            }
            return false;
        }

        public bool AddData(params object[] data)
        {
            return true;
        }
        public bool AddData(LogDataEntry data)
        {
            return true;
        }
        public bool DeleteAllData()
        {
            lock (lockObject)
            {
                dtLogAllData.Clear();
                dsLog.Clear();
                return true;
            }
            
        }

        public bool DeleteData(int index)
        {
            if(index <= dtLogAllData.Rows.Count)
            {
                DataRow rowToRemove = dtLogAllData.Rows[index];
                foreach(DataTable dt in dsLog.Tables)
                {
                    if(dt.TableName == rowToRemove["ChipAddr"].ToString())
                    {
                        DataRow[] rows = dt.Select();
                        foreach(DataRow row in rows)
                        {
                            if (rowToRemove["Time"] == row["Time"])
                            {
                                dt.Rows.Remove(row);
                                dtLogAllData.Rows.Remove(rowToRemove);                               
                                return true;
                            }
                        }
                    }
                }
                return true;
            }
            

            return false;
        }

        /// <summary>
        /// /save as csv
        /// </summary>
        /// <param name="dataSet"></param>
        /// <param name="filePath"></param>
        public void SaveDataSetToCsv<T>(T data, string filePath)
        {
            if(data is DataSet)
            {
                DataSet dataSet = data as DataSet;
                // 创建一个新的 StringWriter 用于写入 CSV 内容
                using (StringWriter sw = new StringWriter())
                {
                    foreach (DataTable dataTable in dataSet.Tables)
                    {
                        sw.WriteLine(dataTable.TableName);
                        // 写入表头
                        sw.WriteLine(string.Join(",", dataTable.Columns.Cast<DataColumn>().Select(column => column.ColumnName)));

                        // 写入每一行数据
                        foreach (DataRow row in dataTable.Rows)
                        {
                            var fields = row.ItemArray.Select(field =>
                            {
                                // 如果字段类型为 int，则转换为十六进制字符串并应用格式
                                if (field is UInt32)
                                {
                                    UInt32 intValue = (UInt32)field;
                                    string s = string.Format("0x{0:X}", intValue); // 使用 X 格式将整数转换为十六进制字符串
                                    return s;
                                }
                                else if(field is UInt16)
                                {
                                    UInt16 intValue = (UInt16)field;
                                    string s = string.Format("0x{0:X}", intValue); // 使用 X 格式将整数转换为十六进制字符串
                                    return s;
                                }
                                // 如果字段类型为 string，则应用双引号和逃逸双引号的格式
                                else if (field is string)
                                {
                                    string s =  string.Concat("\"", field.ToString().Replace("\"", "\"\""), "\"");
                                    return s;
                                }
                                // 其他类型保持不变
                                else
                                {
                                    return field.ToString();
                                }
                            });

                            sw.WriteLine(string.Join(",", fields));
                        }

                        // 添加空行（可选）
                        sw.WriteLine();
                    }
                    try
                    {
                        // 将 StringWriter 中的内容写入到文件中
                        File.WriteAllText(filePath, sw.ToString());
                    }
                    catch (Exception ex)
                    {
                        UIMessageBox.Show(ex.Message);
                    }
                   
                }
            }

            if(data is DataTable)
            {
                DataTable dataTable = data as DataTable;
                using (StringWriter sw = new StringWriter())
                {                    
                    sw.WriteLine(dataTable.TableName);
                    // 写入表头
                    sw.WriteLine(string.Join(",", dataTable.Columns.Cast<DataColumn>().Select(column => column.ColumnName)));

                    // 写入每一行数据
                    foreach (DataRow row in dataTable.Rows)
                    {
                        var fields = row.ItemArray.Select(field =>
                        {
                            // 如果字段类型为 int，则转换为十六进制字符串并应用格式
                            if (field is UInt32)
                            {
                                UInt32 intValue = (UInt32)field;
                                string s = string.Format("0x{0:X}", intValue); // 使用 X 格式将整数转换为十六进制字符串
                                return s;
                            }
                            else if (field is UInt16)
                            {
                                UInt16 intValue = (UInt16)field;
                                string s = string.Format("0x{0:X}", intValue); // 使用 X 格式将整数转换为十六进制字符串
                                return s;
                            }
                            // 如果字段类型为 string，则应用双引号和逃逸双引号的格式
                            else if (field is string)
                            {
                                string s = string.Concat("\"", field.ToString().Replace("\"", "\"\""), "\"");
                                return s;
                            }
                            // 其他类型保持不变
                            else
                            {
                                return field.ToString();
                            }
                        });

                        sw.WriteLine(string.Join(",", fields));
                    }

                    // 添加空行（可选）
                    sw.WriteLine();
                    try
                    {
                        // 将 StringWriter 中的内容写入到文件中
                        File.WriteAllText(filePath, sw.ToString());
                    }
                    catch (Exception ex)
                    {
                        UIMessageBox.Show(ex.Message);
                    }
                }                
            }          
        }
        /// <summary>
        /// save as excel
        /// </summary>
        /// <param name="dataSet"></param>
        /// <param name="filePath"></param>
        public void SaveDataSetToExcel<T>(T data, string filePath)
        {
            if(data is DataSet)
            {
                DataSet dataSet = data as DataSet;
                ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
                try
                {
                    using (ExcelPackage package = new ExcelPackage())
                    {
                        foreach (DataTable dataTable in dataSet.Tables)
                        {
                            // 添加一个工作表
                            ExcelWorksheet worksheet = package.Workbook.Worksheets.Add(dataTable.TableName);
                            worksheet.Name = string.Format("0x{0}", Convert.ToUInt32(dataTable.TableName).ToString("X"));
                            // 写入表头
                            for (int i = 0; i < dataTable.Columns.Count; i++)
                            {
                                worksheet.Cells[1, i + 1].Value = dataTable.Columns[i].ColumnName;
                            }

                            // 写入每一行数据
                            for (int rowIdx = 0; rowIdx < dataTable.Rows.Count; rowIdx++)
                            {
                                var dataRow = dataTable.Rows[rowIdx];
                                for (int colIdx = 0; colIdx < dataTable.Columns.Count; colIdx++)
                                {
                                    object cellValue = dataRow[colIdx];
                                    if (colIdx == 0) // 判断当前单元格的值是否为整数
                                    {
                                        worksheet.Cells[rowIdx + 2, colIdx + 1].Value = string.Format("Ox{0}", ((UInt32)cellValue).ToString("X2"));
                                    }
                                    else if(colIdx == 2)
                                    {
                                        worksheet.Cells[rowIdx + 2, colIdx + 1].Value = string.Format("Ox{0}", ((UInt16)cellValue).ToString("X4")); // 将整数转换为十六进制字符串
                                    }
                                    else if(colIdx == 3)
                                    {
                                        worksheet.Cells[rowIdx + 2, colIdx + 1].Value = string.Format("Ox{0}", ((string)cellValue).PadLeft(8,'0')) ;
                                    }
                                    else
                                    {
                                        worksheet.Cells[rowIdx + 2, colIdx + 1].Value = cellValue; // 直接写入单元格
                                    }
                                }
                            }
                        }
                        try
                        {
                            // 保存 Excel 文件
                            package.SaveAs(new FileInfo(filePath));
                        }
                        catch (Exception ex)
                        {
                            UIMessageBox.Show(ex.Message);
                        }


                    }
                }
                catch (Exception ex)
                {
                    UIMessageBox.Show(ex.Message);
                }
            }

            if(data is DataTable)
            {
                DataTable dataTable = data as DataTable;
                ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
                try
                {
                    using(ExcelPackage package = new ExcelPackage())
                    {
                        // 添加一个工作表
                        ExcelWorksheet worksheet = package.Workbook.Worksheets.Add(dataTable.TableName);
                        worksheet.Name = (dataTable.TableName);
                        // 写入表头
                        for (int i = 0; i < dataTable.Columns.Count; i++)
                        {
                            worksheet.Cells[1, i + 1].Value = dataTable.Columns[i].ColumnName;
                        }

                        // 写入每一行数据
                        for (int rowIdx = 0; rowIdx < dataTable.Rows.Count; rowIdx++)
                        {
                            var dataRow = dataTable.Rows[rowIdx];
                            for (int colIdx = 0; colIdx < dataTable.Columns.Count; colIdx++)
                            {
                                object cellValue = dataRow[colIdx];
                                if (colIdx == 0) // 判断当前单元格的值是否为整数
                                {
                                    worksheet.Cells[rowIdx + 2, colIdx + 1].Value = string.Format("Ox{0}", ((UInt32)cellValue).ToString("X2"));
                                }
                                else if (colIdx == 2)
                                {
                                    worksheet.Cells[rowIdx + 2, colIdx + 1].Value = string.Format("Ox{0}", ((UInt16)cellValue).ToString("X4")); // 将整数转换为十六进制字符串
                                }
                                else if (colIdx == 3)
                                {
                                    worksheet.Cells[rowIdx + 2, colIdx + 1].Value = string.Format("Ox{0}", ((string)cellValue).PadLeft(8, '0'));
                                }
                                else
                                {
                                    worksheet.Cells[rowIdx + 2, colIdx + 1].Value = cellValue; // 直接写入单元格
                                }
                            }
                        }
                        try
                        {
                            // 保存 Excel 文件
                            package.SaveAs(new FileInfo(filePath));
                        }
                        catch (Exception ex)
                        {
                            UIMessageBox.Show(ex.Message);
                        }
                    }
                }
                catch (Exception ex)
                {
                    UIMessageBox.Show(ex.Message);
                }
            }
            
            
        }
        public static void StartMonitoring()
        {
            isMonitoring = true;
            cancellationTokenSource = new CancellationTokenSource();
            Task.Run(() => MonitorLogNum(cancellationTokenSource.Token), cancellationTokenSource.Token);
        }

        public static void StopMonitoring()
        {
            if (cancellationTokenSource != null)
            {
                cancellationTokenSource.Cancel();
            }
            isMonitoring = false;
        }

        public static void MonitorLogNum(CancellationToken token)
        {
            while(isMonitoring)
            {
                lock (lockObject)
                {
                    if (GetLogNum() > 100000)
                    {
                        string logFolderPath = Path.Combine(Application.StartupPath, "Log");

                        if (!Directory.Exists(logFolderPath))
                        {
                            Directory.CreateDirectory(logFolderPath);
                        }
                        string currentTime = DateTime.Now.ToString("yyyy-mm-dd HH-mm-ss");
                        // 获取用户选择的文件路径
                        string filePath = System.IO.Path.Combine(logFolderPath, currentTime + ".xlsx");

                        //调用 SaveDataSetToExcel 方法，将 DataSet 保存为 Excel 文件
                        //instance.SaveDataSetToExcel(instance.GetDataSet, filePath);
                        //不能使用invoke，使用invoke会导致死锁，invoke需要等待instance.DeleteAllData执行完毕，但是由于MonitorLogNum已经在UI线程上执行，UI线程已经被阻塞，无法执行instance.DeleteAllData
                        //这就导致了死锁，UI线程被阻塞自己。
                        UIDispatcher.OnUIThread(() =>
                        {
                            instance.SaveDataSetToExcel(instance.GetDataSet, filePath);
                            instance.DeleteAllData();
                        });
                        //return true;
                     
                    }
                }
                Thread.Sleep(1000);
            }
            //return false;
        }
        public static int GetLogNum()
        {
            return instance.GetDataTableAllData.Rows.Count;
        }
        public static void StartMonitorLogNum()
        {
            if(isMonitoring == false)
            {
                isMonitoring = true;
                monitorLogNumThread = new Thread(() =>
                {
                    //monitorLogNumResult = MonitorLogNum();
                    if (monitorLogNumResult == true)
                    {
                        //Form form = Application.OpenForms[0];
                        //form.Invoke((MethodInvoker)delegate
                        //{
                        //    string logFolderPath = Path.Combine(Application.StartupPath, "Log");

                        //    if (!Directory.Exists(logFolderPath))
                        //    {
                        //        Directory.CreateDirectory(logFolderPath);
                        //    }
                        //    string currentTime = DateTime.Now.ToString("yyyy-mm-dd HH-mm-ss");
                        //    // 获取用户选择的文件路径
                        //    string filePath = System.IO.Path.Combine(logFolderPath, currentTime + ".xlsx");
                        //    instance.SaveDataSetToExcel(instance.GetDataSet, filePath);
                        //    instance.DeleteAllData();
                        //    isMonitoring =false;
                        //    monitorLogNumResult = false;
                        //});
                    }
                });
                monitorLogNumThread.Start();
            }
            
        }

        public static void StopMonitorLogNum()
        {
            isMonitoring = false;
            monitorLogNumThread.Join();
        }
    }
}
